﻿using RegexBuilder.Enums;
using RegexBuilder.Extentions;
using RegexBuilder.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace RegexBuilder
{
    /// <summary>
    /// 建造者
    /// </summary>
    public class RegexBuilder : IRegexBuilder, IRegexBuilderStarter, IRegexStringProvider
    {
        /// <summary>
        /// 静态创建建造器
        /// </summary>
        /// <returns></returns>
        public static IRegexBuilderStarter CreateBuilder()
        {
            return new RegexBuilder();
        }
        /// <summary>
        /// 正则项列表
        /// </summary>
        private List<RegexBasePattern> Patterns = new List<RegexBasePattern>();
        /// <summary>
        /// 当前操作的正则项
        /// </summary>
        private RegexBasePattern? CurrentPattern => Patterns.LastOrDefault();
        /// <summary>
        /// 匹配开头
        /// </summary>
        private bool MatchAhead { get; set; }
        /// <summary>
        /// 匹配结尾
        /// </summary>
        private bool MatchTail { get; set; }
        /// <summary>
        /// 创建新的正则项
        /// </summary>
        private void CreateNewPattern()
        {
            Patterns.Add(new RegexBasePattern());
        }

        public IRegexBuilder SetGreedy(bool Greedy = true)
        {
            CurrentPattern!.IsGreedy = Greedy;
            return this;
        }

        public IRegexBuilder SetMatchTimes(uint times)
        {
            return SetMatchRange(times, times);
        }
        public IRegexBuilder SetMatchRange(uint? least, uint? most)
        {
            CurrentPattern!.LeastTimes = least;
            CurrentPattern!.MostTimes = most < least?least: most;
            return this;
        }

        public IRegexBuilder LookAheadPositiveAssert(Action<IRegexBuilderStarter> PatternBuilder)
        {
            var builder = CreateBuilder();
            PatternBuilder(builder);
            CurrentPattern!.LookBehindPositiveAssert = builder;
            return this;
        }

        public IRegexBuilder LookAheadNegativeAssert(Action<IRegexBuilderStarter> PatternBuilder)
        {
            var builder = CreateBuilder();
            PatternBuilder(builder);
            CurrentPattern!.LookAheadNegativeAssert = builder;
            return this;
        }

        public IRegexBuilder LookBehindPositiveAssert(Action<IRegexBuilderStarter> PatternBuilder)
        {
            var builder = CreateBuilder();
            PatternBuilder(builder);
            CurrentPattern!.LookBehindPositiveAssert = builder;
            return this;
        }

        public IRegexBuilder LookBehindNegativeAssert(Action<IRegexBuilderStarter> PatternBuilder)
        {
            var builder = CreateBuilder();
            PatternBuilder(builder);
            CurrentPattern!.LookBehindNegativeAssert = builder;
            return this;
        }
        public string ToRegexString()
        {
            ///判断是否添加首尾匹配标记
            var regexString = GetInerRegex();
            if (MatchAhead && MatchTail)
            {
                return $"^{regexString}$";
            }
            else if (MatchAhead)
            {
                return $"^{regexString}";
            }
            else if (MatchTail)
            {
                return $"{regexString}$";
            }
            else
            {
                return regexString;
            }
        }
        public string GetInerRegex()
        {
            var regexs = Patterns.Select(x => x.ToRegexString());

            var regexString = string.Join(null, regexs);
            return regexString;
        }
        /// <summary>
        /// 重写转字符串
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return ToRegexString();
        }

        /// <summary>
        /// 将字符串数组全部字符串进行转义
        /// </summary>
        private Func<IEnumerable<string>, IEnumerable<string>?> stringArrayEscape =
            stringarray => stringarray?.Select(x => x.ToCharArray())
                                .Select(x => x.Select(y => y.CharToEscape()))
                                .Select(x => String.Join(null, x.Distinct()));
        /// <summary>
        /// 将字符串进行特殊字符转义
        /// </summary>
        private Func<string, string> stringEscape = str => str != null ? string.Join(null, str?.ToCharArray().Select(x => x.CharToEscape()).Distinct()) : "";

        /// <summary>
        /// 将char数组转义为字符串
        /// </summary>
        private Func<IEnumerable<char>, string> charArrayToEscape = charArray => charArray != null ? string.Join(null, charArray?.Select(x => x.CharToEscape()).Distinct()) : "";
        #region IRegexBuilderStarter         
        IRegexBuilder IRegexBuilderStarter.AddPattern(CharSetEnum charSet, IEnumerable<char>? Includechars, IEnumerable<char>? excludechars)
        {
            CreateNewPattern();
            CurrentPattern!.Pattern = charSet.GetPattern(charArrayToEscape(Includechars!), charArrayToEscape(excludechars!));
            return this;
        }
        IRegexBuilder IRegexBuilderStarter.AddCharSetPattern(IEnumerable<char>? Includechars, IEnumerable<char>? excludechars)
        {
            CreateNewPattern();
            var includeCounts = Includechars?.Count();
            var excludeCounts = excludechars?.Count();
            if (includeCounts > 0 && excludeCounts > 0)
            {
                CurrentPattern!.Pattern = $"([{ charArrayToEscape(Includechars!)}]|[^{charArrayToEscape(excludechars!)}])";
            }
            else if (includeCounts > 0)
            {
                CurrentPattern!.Pattern = $"[{charArrayToEscape(Includechars!)}]";
            }
            else if (excludeCounts > 0)
            {
                CurrentPattern!.Pattern = $"[^{charArrayToEscape(excludechars!)}]";
            }
            return this;
        }


        IRegexBuilder IRegexBuilderStarter.AddPattern(params string[] Strings)
        {
            //Todo:处理转义字符
            CreateNewPattern();
            var regex = string.Join("|", stringArrayEscape(Strings));
            if (regex.Length==1)
            {
                CurrentPattern!.Pattern = $"{regex}";
            }else
            {
                CurrentPattern!.Pattern = $"({regex})";
            }
            return this;
        }

        IRegexBuilder IRegexBuilderStarter.AddPattern(IEnumerable<string> Strings)
        {
            //Todo:处理转义字符
            CreateNewPattern();
            CurrentPattern!.Pattern = $"({string.Join("|", stringArrayEscape(Strings))})";
            return this;
        }

        IRegexBuilderStarter IRegexBuilderStarter.AddRegexPattern(string regex)
        {
            CreateNewPattern();
            CurrentPattern!.Pattern = regex;
            CurrentPattern!.IsRawRegexString = true;
            return this;
        }

        IRegexBuilder IRegexBuilderStarter.AddOptionPattern(Action<IList<IRegexBuilderStarter>> Makebuilders, int Count)
        {
            List<IRegexBuilderStarter> list = new List<IRegexBuilderStarter>();
            for (int i = 0; i < Count; i++)
            {
                list.Add(new RegexBuilder());
            }
            Makebuilders(list);
            var regexs = list.Select(x => x.ToRegexString());
            var result = string.Join("|", regexs);

            Patterns.Add(new RegexBasePattern());
            CurrentPattern!.Pattern = $"({result})";
            return this;
        }

        IRegexBuilder IRegexBuilderStarter.AddIncludeCharSetPattern(IEnumerable<char> includechars)
        {
            CreateNewPattern();
            CurrentPattern!.Pattern = $"[{charArrayToEscape(includechars)}]";
            return this;
        }
        IRegexBuilder IRegexBuilderStarter.AddExcludeCharSetPattern(IEnumerable<char> excludechars)
        {
            CreateNewPattern();
            CurrentPattern!.Pattern = $"[^{charArrayToEscape(excludechars)}]";
            return this;
        }
        string IRegexStringProvider.ToRegexString()
        {
            return ToRegexString();
        }


        #endregion
    }
}

